using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace SqlTools.CodeGenerator.Data
{
	public class ForeignKeyTableProperty : TableProperty
	{
		private string _referenceObjectFieldName;
		private string _referenceObjectPropertyName;
		private string _foreignFieldName;
		private string _foreignPropertyName;
		
		private bool _ignoreForeign;
		private bool _ignoreReference;

		private string _foreignObjectFieldName;
		private string _foreignObjectPropertyName;

		private Table _referenceTable;
		private string _referenceColumnName;
		private Table _foreignKeyTable;
		private string _foreignKeyColumnName;

		protected Method _foreignRetrieve;
		private Method _referenceRetrieve;

		private FKLoadResolution _tempLoadResolution;

		public ForeignKeyTableProperty(string name, Table table, string columnName)
			: base(name, table, columnName)
		{
			_referenceObjectFieldName = "";
			_referenceObjectPropertyName = "";

			_foreignFieldName = "";
			_foreignPropertyName = "";
			_foreignObjectFieldName = "";
			_foreignObjectPropertyName = "";

			_ignoreForeign = false;
			_ignoreReference = false;

			_referenceTable = null;
			_referenceColumnName = "";
			_foreignKeyTable = null;
			_foreignKeyColumnName = "";

			_foreignRetrieve = null;
			_referenceRetrieve = null;
		}

		public override TablePropertyType Type
		{
			get { return TablePropertyType.ForeignKey; }
		}

		public string ForeignObjectPropertyName
		{
			get { return _foreignObjectPropertyName; }
			set { _foreignObjectPropertyName = value; }
		}

		public string ForeignObjectFieldName
		{
			get { return _foreignObjectFieldName; }
			set { _foreignObjectFieldName = value; }
		}

		public string ReferenceFieldName
		{
			get { return _fieldName; }
			set { _fieldName = value; }
		}

		public string ReferencePropertyName
		{
			get { return _propertyName; }
			set { _propertyName = value; }
		}

		public Table ReferenceTable
		{
			get { return _referenceTable; }
			set { _referenceTable = value; }
		}

		public string ReferenceColumnName
		{
			get { return _referenceColumnName; }
			set { _referenceColumnName = value; }
		}

		public string ReferenceObjectFieldName
		{
			get { return _referenceObjectFieldName; }
			set { _referenceObjectFieldName = value; }
		}

		public string ReferenceObjectPropertyName
		{
			get { return _referenceObjectPropertyName; }
			set { _referenceObjectPropertyName = value; }
		}

		public string ForeignFieldName
		{
			get { return _foreignFieldName; }
			set { _foreignFieldName = value; }
		}

		public string ForeignPropertyName
		{
			get { return _foreignPropertyName; }
			set { _foreignPropertyName = value; }
		}

		public bool IgnoreForeign
		{
			get { return _ignoreForeign; }
			set { _ignoreForeign = value; }
		}

		public bool IgnoreReference
		{
			get { return _ignoreReference; }
			set { _ignoreReference = value; }
		}

		public Table ForeignKeyTable
		{
			get { return _foreignKeyTable; }
			set { _foreignKeyTable = value; }
		}

		public string ForeignKeyColumnName
		{
			get { return _foreignKeyColumnName; }
			set { _foreignKeyColumnName = value; }
		}

		public Method ForeignRetrieve
		{
			get { return _foreignRetrieve; }
			set { _foreignRetrieve = value; }
		}

		public Method ReferenceRetrieve
		{
			get { return _referenceRetrieve; }
			set { _referenceRetrieve = value; }
		}

		public override XmlElement CreateXmlElement(XmlDocument doc)
		{
			XmlElement xmlFK = base.CreateXmlElement(doc);

			xmlFK.Attributes.Append(doc.CreateAttribute("ReferenceObjectFieldName")).Value = _referenceObjectFieldName;
			xmlFK.Attributes.Append(doc.CreateAttribute("ReferenceObjectPropertyName")).Value = _referenceObjectPropertyName;
			xmlFK.Attributes.Append(doc.CreateAttribute("ReferenceFieldName")).Value = _fieldName;
			xmlFK.Attributes.Append(doc.CreateAttribute("ReferencePropertyName")).Value = _propertyName;

			xmlFK.Attributes.Append(doc.CreateAttribute("ForeignFieldName")).Value = _foreignFieldName;
			xmlFK.Attributes.Append(doc.CreateAttribute("ForeignPropertyName")).Value = _referenceObjectPropertyName;
			xmlFK.Attributes.Append(doc.CreateAttribute("ForeignObjectFieldName")).Value = _foreignObjectFieldName;
			xmlFK.Attributes.Append(doc.CreateAttribute("ForeignObjectPropertyName")).Value = _foreignObjectPropertyName;

			xmlFK.Attributes.Append(doc.CreateAttribute("IgnoreForeign")).Value = _ignoreForeign.ToString();
			xmlFK.Attributes.Append(doc.CreateAttribute("IgnoreReference")).Value = _ignoreReference.ToString();

			if ( _referenceTable != null )
				xmlFK.Attributes.Append(doc.CreateAttribute("ReferenceTable")).Value = _referenceTable.TableName;
			if ( _referenceColumnName != null )
				xmlFK.Attributes.Append(doc.CreateAttribute("ReferenceColumnName")).Value = _referenceColumnName;

			if ( _foreignKeyTable != null )
				xmlFK.Attributes.Append(doc.CreateAttribute("ForeignKeyTable")).Value = _foreignKeyTable.TableName;
			if ( _foreignKeyColumnName != null )
				xmlFK.Attributes.Append(doc.CreateAttribute("ForeignKeyColumnName")).Value = _foreignKeyColumnName;


			if ( _foreignRetrieve != null )
				xmlFK.Attributes.Append(doc.CreateAttribute("ForeignRetrieve")).Value = _foreignRetrieve.MethodName;
			if ( _referenceRetrieve != null )
				xmlFK.Attributes.Append(doc.CreateAttribute("ReferenceRetrieveByPK")).Value = _referenceRetrieve.MethodName;

			return xmlFK;
		}

		public override void LoadXml(XmlElement xmlProp)
		{
			base.LoadXml(xmlProp);

			_referenceObjectFieldName = xmlProp.GetAttribute("ReferenceObjectFieldName");
			_referenceObjectPropertyName = xmlProp.GetAttribute("ReferenceObjectPropertyName");
			_fieldName = xmlProp.GetAttribute("ReferenceFieldName");
			_propertyName = xmlProp.GetAttribute("ReferencePropertyName");

			_foreignFieldName = xmlProp.GetAttribute("ForeignFieldName");
			_foreignPropertyName = xmlProp.GetAttribute("ForeignPropertyName");
			_foreignObjectFieldName = xmlProp.GetAttribute("ForeignObjectFieldName");
			_foreignObjectPropertyName = xmlProp.GetAttribute("ForeignObjectPropertyName");

			

			string temp = "";

			temp = xmlProp.GetAttribute("IgnoreForeign");
			if ( !bool.TryParse(temp, out _ignoreForeign) )
				_ignoreForeign = false;

			temp = xmlProp.GetAttribute("IgnoreReference");
			if ( !bool.TryParse(temp, out _ignoreReference) )
				_ignoreReference = false;

			temp = xmlProp.GetAttribute("ReferenceTable");
			_tempLoadResolution._referenceTable = temp;

			temp = xmlProp.GetAttribute("ReferenceColumnName");
			_referenceColumnName = temp;
			

			temp = xmlProp.GetAttribute("ForeignKeyTable");
			_tempLoadResolution._foreignKeyTable = temp;

			temp = xmlProp.GetAttribute("ForeignKeyColumnName");
			_foreignKeyColumnName = temp;


			temp = xmlProp.GetAttribute("ForeignRetrieve");
			_tempLoadResolution._foreignRetreive = temp;

			temp = xmlProp.GetAttribute("ReferenceRetrieveByPK");
			_tempLoadResolution._referenceRetrieve = temp;
		}

		public void LoadResolve()
		{
			_referenceTable = _table.Project.Tables[_tempLoadResolution._referenceTable];
			_foreignKeyTable = _table.Project.Tables[_tempLoadResolution._foreignKeyTable];

			_referenceRetrieve = _referenceTable.Methods[_tempLoadResolution._referenceRetrieve];
			_foreignRetrieve = _foreignKeyTable.Methods[_tempLoadResolution._foreignRetreive];
		}

		public IntrinsicTableProperty ConvertToIntrinsic()
		{
			IntrinsicTableProperty itp = new IntrinsicTableProperty(_propertyName, _table, _columnName);
			itp.AutoGeneratedOnInsert = _autoGeneratedOnInsert;
			itp.DataLength = _dataLength;
			itp.DataType = _datatype;
			itp.DefaultValue = _defaultValue;
			itp.FieldName = _fieldName;
			itp.Nullable = _nullable;

			return itp;
		}

		protected struct FKLoadResolution
		{
			public string _referenceTable;
			public string _foreignKeyTable;

			public string _referenceRetrieve;
			public string _foreignRetreive;
		}
	}
}
